Commits

Anonymous committed 5506adf

Implementing breakOnNull option to not draw line/bar when have null value rather than skipping point.

  • Participants
  • Parent commits 052bc9e

Comments (0)

Files changed (7)

examples/barTest.html

 <html lang="en">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-  <title>Simple Test</title>
+  <title>Bar Charts</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" />

examples/missingValues.html

+<!DOCTYPE html>
+
+<html lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Null Value Handling</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>
+  <script language="javascript" type="text/javascript" src="../src/plugins/jqplot.categoryAxisRenderer.js"></script>
+  <!-- END: load jqplot -->
+  <style type="text/css">
+    .jqplot-target {
+        margin-bottom: 2em;
+    }
+    
+    pre {
+        background: #D8F4DC;
+        border: 1px solid rgb(200, 200, 200);
+        padding-top: 1em;
+        padding-left: 3em;
+        padding-bottom: 1em;
+        margin-top: 1em;
+        margin-bottom: 4em;
+        
+    }
+    
+    p {
+        margin: 2em 0;
+    }
+    
+    .note {
+        font-size: 0.8em;
+    }
+  </style>
+
+<script class="code" language="javascript" type="text/javascript">$(document).ready(function(){
+    s1 = [23, 53, 13, null, 18, 25, 26, 41, 42, null, null, null, 37, 29, 27, 19];
+
+    plot1 = $.jqplot('chart1',[s1],{
+        title: 'Default Line, ignore nulls'
+    });
+});</script>
+
+<script class="code" language="javascript" type="text/javascript">$(document).ready(function(){
+   s1 = [23, 53, 13, null, 18, 25, 26, 41, 42, null, null, null, 37, 29, 27, 19];
+
+   plot1b = $.jqplot('chart1b',[s1],{
+       title: 'breakOnNull true, Nulls Break Line',
+        series:[
+            {breakOnNull: true}
+        ]
+   });
+});</script>
+
+    
+<script class="code" type="text/javascript">$(document).ready(function(){
+    plot2 = $.jqplot('chart2', [[[1,2], [2,null], [3,7], [4,10]]], {
+        captureRightClick: true,
+        seriesDefaults:{
+            renderer:$.jqplot.BarRenderer
+        },
+        axes: {
+            xaxis: {
+                renderer: $.jqplot.CategoryAxisRenderer
+            }
+        }
+    });
+});</script>
+
+    
+<script class="code" type="text/javascript">$(document).ready(function(){
+    plot2b = $.jqplot('chart2b', [[[1,2], [2,null], [3,7], [4,10]]], {
+        captureRightClick: true,
+        seriesDefaults:{
+            renderer:$.jqplot.BarRenderer,
+            breakOnNull: true
+        },
+        axes: {
+            xaxis: {
+                renderer: $.jqplot.CategoryAxisRenderer
+            }
+        }
+    });
+});</script>
+
+    <script type="text/javascript">    
+        $(document).ready(function(){
+            $('script.code').each(function(index) {
+                $('pre.code').eq(index).text($(this).html());
+            });
+            $('script.common').each(function(index) {
+                $('pre.common').eq(index).html($(this).html());
+            });
+            $(document).unload(function() {$('*').unbind(); });
+        });
+    </script>
+  </head>
+  <body>
+<?php include "nav.inc"; ?>
+    <div id="chart1" style="margin-top:20px; margin-left:20px; width:500px; height:300px;"></div>
+<pre class="code"></pre>
+    <div id="chart1b" style="margin-top:20px; margin-left:20px; width:500px; height:300px;"></div>
+<pre class="code"></pre>
+    <div id="chart2" style="margin-top:20px; margin-left:20px; width:500px; height:300px;"></div>
+<pre class="code"></pre>
+    <div id="chart2b" style="margin-top:20px; margin-left:20px; width:500px; height:300px;"></div>
+<pre class="code"></pre>
+  </body>
+</html>

src/jqplot.core.js

             return {offsets:go, gridPos:gridPos, dataPos:dataPos};
         }
         
-        function getNeighborPoint(plot, x, y) {
-            var ret = null;
-            var s, i, d0, d, j, r, k;
-            var threshold, t;
-            for (var k=plot.seriesStack.length-1; k>-1; k--) {
-                i = plot.seriesStack[k];
-                s = plot.series[i];
-                r = s.renderer;
-                if (s.show) {
-                    t = s.markerRenderer.size/2+s.neighborThreshold;
-                    threshold = (t > 0) ? t : 0;
-                    for (var j=0; j<s.gridData.length; j++) {
-                        p = s.gridData[j];
-                        // neighbor looks different to OHLC chart.
-                        if (r.constructor == $.jqplot.OHLCRenderer) {
-                            if (r.candleStick) {
-                                var yp = s._yaxis.series_u2p;
-                                if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {
-                                    return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};
-                                }
-                            }
-                            // if an open hi low close chart
-                            else if (!r.hlc){
-                                var yp = s._yaxis.series_u2p;
-                                if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {
-                                    return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};
-                                }
-                            }
-                            // a hi low close chart
-                            else {
-                                var yp = s._yaxis.series_u2p;
-                                if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][1]) && y <= yp(s.data[j][2])) {
-                                    return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};
-                                }
-                            }
-                            
-                        }
-                        else {
-                            d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) );
-                            if (d <= threshold && (d <= d0 || d0 == null)) {
-                               d0 = d;
-                               return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};
-                            }
-                        }
-                    } 
-                }
-            }
-            return ret;
-        }
+        // function getNeighborPoint(plot, x, y) {
+        //     var ret = null;
+        //     var s, i, d0, d, j, r, k;
+        //     var threshold, t;
+        //     for (var k=plot.seriesStack.length-1; k>-1; k--) {
+        //         i = plot.seriesStack[k];
+        //         s = plot.series[i];
+        //         r = s.renderer;
+        //         if (s.show) {
+        //             t = s.markerRenderer.size/2+s.neighborThreshold;
+        //             threshold = (t > 0) ? t : 0;
+        //             for (var j=0; j<s.gridData.length; j++) {
+        //                 p = s.gridData[j];
+        //                 // neighbor looks different to OHLC chart.
+        //                 if (r.constructor == $.jqplot.OHLCRenderer) {
+        //                     if (r.candleStick) {
+        //                         var yp = s._yaxis.series_u2p;
+        //                         if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {
+        //                             return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};
+        //                         }
+        //                     }
+        //                     // if an open hi low close chart
+        //                     else if (!r.hlc){
+        //                         var yp = s._yaxis.series_u2p;
+        //                         if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {
+        //                             return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};
+        //                         }
+        //                     }
+        //                     // a hi low close chart
+        //                     else {
+        //                         var yp = s._yaxis.series_u2p;
+        //                         if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][1]) && y <= yp(s.data[j][2])) {
+        //                             return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};
+        //                         }
+        //                     }
+        //                     
+        //                 }
+        //                 else {
+        //                     d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) );
+        //                     if (d <= threshold && (d <= d0 || d0 == null)) {
+        //                        d0 = d;
+        //                        return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};
+        //                     }
+        //                 }
+        //             } 
+        //         }
+        //     }
+        //     return ret;
+        // }
         
         
         // function to check if event location is over a area area
                         r = s.renderer;
                         if (s.show) {
                             if (s.fill) {
-                                x = gridpos.x;
-                                y = gridpos.y;
                                 // first check if it is in bounding box
                                 var inside = false;
                                 if (x>s._boundingBox[0][0] && x<s._boundingBox[1][0] && y>s._boundingBox[1][1] && y<s._boundingBox[0][1]) { 
                                         }
                             
                                     }
-                                    else {
+                                    else if (p[0] != null && p[1] != null){
                                         d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) );
                                         if (d <= threshold && (d <= d0 || d0 == null)) {
                                            d0 = d;

src/jqplot.lineRenderer.js

         this.gridData = [];
         this._prevGridData = [];
         for (var i=0; i<this.data.length; i++) {
-            if (data[i] != null) {
+            // if not a line series or if no nulls in data, push the converted point onto the array.
+            if (data[i][0] != null && data[i][1] != null) {
                 this.gridData.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1])]);
             }
-            if (pdata[i] != null) {
+            // else if there is a null, preserve it.
+            else if (data[i][0] == null) {
+                this.gridData.push([null, yp.call(this._yaxis, data[i][1])]);
+            }
+            else if (data[i][1] == null) {
+                this.gridData.push([xp.call(this._xaxis, data[i][0]), null]);
+            }
+            // if not a line series or if no nulls in data, push the converted point onto the array.
+            if (pdata[i] && pdata[i][0] != null && pdata[i][1] != null) {
                 this._prevGridData.push([xp.call(this._xaxis, pdata[i][0]), yp.call(this._yaxis, pdata[i][1])]);
             }
+            // else if there is a null, preserve it.
+            else if (pdata[i] && pdata[i][0] == null) {
+                this._prevGridData.push([null, yp.call(this._yaxis, pdata[i][1])]);
+            }  
+            else if (pdata[i] && pdata[i][0] != null && pdata[i][1] != null) {
+                this._prevGridData.push([xp.call(this._xaxis, pdata[i][0]), null]);
+            }
         }
     };
     
         var gd = [];
         var pgd = [];
         for (var i=0; i<data.length; i++) {
-            if (data[i] != null) {
+            // if not a line series or if no nulls in data, push the converted point onto the array.
+            if (data[i][0] != null && data[i][1] != null) {
                 gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1])]);
             }
+            // else if there is a null, preserve it.
+            else if (data[i][0] == null) {
+                gd.push([null, yp.call(this._yaxis, data[i][1])]);
+            }
+            else if (data[i][1] == null) {
+                gd.push([xp.call(this._xaxis, data[i][0]), null]);
+            }
         }
         return gd;
     };
                             this.renderer.shapeRenderer.draw(ctx, gd, opts);
                         }
                     }
+                    /////////////////////////
+                    // Not filled to zero
+                    ////////////////////////
                     else {                    
                         // if stoking line as well as filling, get a copy of line data.
                         if (fillAndStroke) {
             // now draw the markers
             if (this.markerRenderer.show && !fill) {
                 for (i=0; i<gd.length; i++) {
-                    this.markerRenderer.draw(gd[i][0], gd[i][1], ctx, opts.markerOptions);
+                    if (gd[i][0] != null && gd[i][1] != null) {
+                        this.markerRenderer.draw(gd[i][0], gd[i][1], ctx, opts.markerOptions);
+                    }
                 }
             }
         }

src/jqplot.linearAxisRenderer.js

             
             for (var j=0; j<d.length; j++) { 
                 if (this.name == 'xaxis' || this.name == 'x2axis') {
-                    if (d[j][0] < db.min || db.min == null) {
+                    if ((d[j][0] != null && d[j][0] < db.min) || db.min == null) {
                         db.min = d[j][0];
                     }
-                    if (d[j][0] > db.max || db.max == null) {
+                    if ((d[j][0] != null && d[j][0] > db.max) || db.max == null) {
                         db.max = d[j][0];
                     }
                 }              
                 else {
-                    if (d[j][1] < db.min || db.min == null) {
+                    if ((d[j][1] != null && d[j][1] < db.min) || db.min == null) {
                         db.min = d[j][1];
                     }
-                    if (d[j][1] > db.max || db.max == null) {
+                    if ((d[j][1] != null && d[j][1] > db.max) || db.max == null) {
                         db.max = d[j][1];
                     }
                 }              

src/jqplot.shadowRenderer.js

             else {
                 ctx.moveTo(points[0][0], points[0][1]);
                 for (var i=1; i<points.length; i++) {
-                    ctx.lineTo(points[i][0], points[i][1]);
+                    if (points[i][0] != null && points[i][1] != null) {
+                        ctx.lineTo(points[i][0], points[i][1]);                        
+                    }
+                    // if null value, skip ahead a point and move to it
+                    else {
+                        i++;
+                        if (i < points.length) {
+                            ctx.moveTo(points[i][0], points[i][1]);
+                        }
+                    }
                 }
                 
             }

src/jqplot.shapeRenderer.js

         else {
             ctx.moveTo(points[0][0], points[0][1]);
             for (var i=1; i<points.length; i++) {
-                ctx.lineTo(points[i][0], points[i][1]);
+                if (points[i][0] != null && points[i][1] != null) {
+                    ctx.lineTo(points[i][0], points[i][1]);                        
+                }
+                // if null value, skip ahead a point and move to it
+                else {
+                    i++;
+                    if (i < points.length) {
+                        ctx.moveTo(points[i][0], points[i][1]);
+                    }
+                }
             }
             if (closePath) {
                 ctx.closePath();