Commits

Anonymous committed 2813c6d

fixed incompatability with event handling when donut or funnel plot on same page as another type of plot. Fixed legendLabels.html example. Replaced getNeighborPoint method in core with checkIntersection so I can use different methods to check for mouse interaction with plot points, slices, areas, etc.

Comments (0)

Files changed (8)

examples/donutTest.html

     <p style="margin-top:40px;">The last example shows a donut with all of the default colors.  Mouse over to see the default highlight colors.  Series colors can be specified with the "seriesColors" option on the plot or on the series.  The highlight colors are specified with the 'highlightColors' option on the series renderer.</p>
     
         <div id="chart5" style="margin-top:20px; margin-left:20px; width:400px; height:400px;"></div>
+        <div id="chart6" style="margin-top:20px; margin-left:20px; width:400px; height:400px;"></div>
   </body>
 </html>

examples/donutTest.js

         }
     });
     
+    plot6 = $.jqplot('chart6', [[1,2,3,4]]);
+    
     $('#chart1').bind('jqplotDataClick', 
         function (ev, seriesIndex, pointIndex, data) {
             $('#info1').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data);

examples/funnelTest.html

     <div><span>You Right Clicked: </span><span id="info3">Nothing yet</span></div>
     
     <div id="chart3" style="margin-top:20px; margin-left:20px; width:300px; height:300px;"></div>
+    
+<p>A small chart to test for plugin compatabiity.</p>
+    <div id="chart4" style="margin-top:20px; margin-left:20px; width:200px; height:100px;"></div>
  
   </body>
 </html>

examples/funnelTest.js

         }
     });
     
+    plot4 = $.jqplot('chart4', [[1,2,3,4]]);
+    
     $('#chart1').bind('jqplotDataClick', 
         function (ev, seriesIndex, pointIndex, data) {
             $('#info1').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data);

examples/legendLabels.html

   <link rel="stylesheet" type="text/css" href="examples.css" />
   
   <!-- BEGIN: load jquery -->
-  <script language="javascript" type="text/javascript" src="../src/jquery-1.4.2.js"></script>
+  <script language="javascript" type="text/javascript" src="../src/jquery-1.4.2.min.js"></script>
   <!-- END: load jquery -->
   
   <!-- BEGIN: load jqplot -->

src/jqplot.core.js

         // After plot has been visibly drawn once, it generally doesn't need redrawn if its
         // container is hidden and shown.
         this._drawCount = 0;
-        // true to run through the getNeighborPoint function.  Some plot types
-        // supply their own neighbor detection (donut, bar, pie), so they don't
-        // want to waste cycles with this routine.
-        this._processGetNeighbor = true;
         // this.doCustomEventBinding = true;
         // prop: drawIfHidden
         // True to execute the draw method even if the plot target is hidden.
             return ret;
         }
         
+        
+        // function to check if event location is over a area area
+        function checkIntersection(gridpos, plot) {
+            var series = plot.series;
+            var i, j, k, s, r, x, y, theta, sm, sa, minang, maxang;
+            var d0, d;
+            var threshold, t;
+            for (k=plot.seriesStack.length-1; k>=0; k--) {
+                i = plot.seriesStack[k];
+                s = series[i];
+                switch (s.renderer.constructor) {
+                    case $.jqplot.DonutRenderer:
+                        sa = s.startAngle/180*Math.PI;
+                        x = gridpos.x - s._center[0];
+                        y = gridpos.y - s._center[1];
+                        r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
+                        if (x > 0 && -y >= 0) {
+                            theta = 2*Math.PI - Math.atan(-y/x);
+                        }
+                        else if (x > 0 && -y < 0) {
+                            theta = -Math.atan(-y/x);
+                        }
+                        else if (x < 0) {
+                            theta = Math.PI - Math.atan(-y/x);
+                        }
+                        else if (x == 0 && -y > 0) {
+                            theta = 3*Math.PI/2;
+                        }
+                        else if (x == 0 && -y < 0) {
+                            theta = Math.PI/2;
+                        }
+                        else if (x == 0 && y == 0) {
+                            theta = 0;
+                        }
+                        if (sa) {
+                            theta -= sa;
+                            if (theta < 0) {
+                                theta += 2*Math.PI;
+                            }
+                            else if (theta > 2*Math.PI) {
+                                theta -= 2*Math.PI;
+                            }
+                        }
+            
+                        sm = s.sliceMargin/180*Math.PI;
+                        if (r < s._radius && r > s._innerRadius) {
+                            for (j=0; j<s.gridData.length; j++) {
+                                minang = (j>0) ? s.gridData[j-1][1]+sm : sm;
+                                maxang = s.gridData[j][1];
+                                if (theta > minang && theta < maxang) {
+                                    return {seriesIndex:s.index, pointIndex:j, gridData:s.gridData[j], data:s.data[j]};
+                                }
+                            }
+                        }
+                        break;
+                        
+                    case $.jqplot.FunnelRenderer:
+                        x = gridpos.x;
+                        y = gridpos.y;
+                        var v = s._vertices,
+                            vfirst = v[0],
+                            vlast = v[v.length-1],
+                            lex,
+                            rex;
+    
+                        // equations of right and left sides, returns x, y values given height of section (y value and 2 points)
+    
+                        function findedge (l, p1 , p2) {
+                            var m = (p1[1] - p2[1])/(p1[0] - p2[0]);
+                            var b = p1[1] - m*p1[0];
+                            var y = l + p1[1];
+        
+                            return [(y - b)/m, y];
+                        }
+    
+                        // check each section
+                        lex = findedge(y, vfirst[0], vlast[3]);
+                        rex = findedge(y, vfirst[1], vlast[2]);
+                        for (j=0; j<v.length; j++) {
+                            cv = v[j];
+                            if (y >= cv[0][1] && y <= cv[3][1] && x >= lex[0] && x <= rex[0]) {
+                                return {seriesIndex:s.index, pointIndex:j, gridData:null, data:s.data[j]};
+                            }
+                        }         
+                        break;           
+                    
+                    default:
+                        x = gridpos.x;
+                        y = gridpos.y;
+                        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]};
+                                    }
+                                }
+                            } 
+                        }
+                        break;
+                }
+            }
+            
+            return null;
+        }
+        
+        
+        
         this.onClick = function(ev) {
             // Event passed in is normalized and will have data attribute.
             // Event passed out is unnormalized.
             var positions = getEventPosition(ev);
             var p = ev.data.plot;
-            var neighbor = (p._processGetNeighbor) ? getNeighborPoint(p, positions.gridPos.x, positions.gridPos.y) : null;
+            var neighbor = checkIntersection(positions.gridPos, p);
             ev.data.plot.eventCanvas._elem.trigger('jqplotClick', [positions.gridPos, positions.dataPos, neighbor, p]);
         };
         
             // Event passed out is unnormalized.
             var positions = getEventPosition(ev);
             var p = ev.data.plot;
-            var neighbor = (p._processGetNeighbor) ? getNeighborPoint(p, positions.gridPos.x, positions.gridPos.y) : null;
+            var neighbor = checkIntersection(positions.gridPos, p);
             ev.data.plot.eventCanvas._elem.trigger('jqplotDblClick', [positions.gridPos, positions.dataPos, neighbor, p]);
         };
         
         this.onMouseDown = function(ev) {
             var positions = getEventPosition(ev);
             var p = ev.data.plot;
-            var neighbor = (p._processGetNeighbor) ? getNeighborPoint(p, positions.gridPos.x, positions.gridPos.y) : null;
+            var neighbor = checkIntersection(positions.gridPos, p);
             p.eventCanvas._elem.trigger('jqplotMouseDown', [positions.gridPos, positions.dataPos, neighbor, p]);
         };
         
         this.onRightClick = function(ev) {
             var positions = getEventPosition(ev);
             var p = ev.data.plot;
-            var neighbor = (p._processGetNeighbor) ? getNeighborPoint(p, positions.gridPos.x, positions.gridPos.y) : null;
+            var neighbor = checkIntersection(positions.gridPos, p);
             if (p.captureRightClick) {
                 if (ev.which == 3) {
                     p.eventCanvas._elem.trigger('jqplotRightClick', [positions.gridPos, positions.dataPos, neighbor, p]);
             var positions = getEventPosition(ev);
             var p = ev.data.plot;
             var p = ev.data.plot;
-            var neighbor = (p._processGetNeighbor) ? getNeighborPoint(p, positions.gridPos.x, positions.gridPos.y) : null;
+            var neighbor = checkIntersection(positions.gridPos, p);
             p.eventCanvas._elem.trigger('jqplotMouseMove', [positions.gridPos, positions.dataPos, neighbor, p]);
         };
         

src/plugins/jqplot.donutRenderer.js

                 }
             }
         }
-        // set the _processGetNeighbor to false, we'll do this in the renderer.
-        this._processGetNeighbor = false;
         this.target.bind('mouseout', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
     }
     
         plot.plugins.donutRenderer.highlightedSeriesIndex = null;
         plot.target.trigger('jqplotDataUnhighlight');
     }
-    
+ 
     function handleMove(ev, gridpos, datapos, neighbor, plot) {
-        var ins = checkIntersection(gridpos, plot);
-        if (ins) {
+        if (neighbor) {
+            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             plot.target.trigger('jqplotDataMouseOver', ins);
             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 plot.target.trigger('jqplotDataHighlight', ins);
                 highlight (plot, ins[0], ins[1]);
             }
         }
-        else if (ins == null) {
+        else if (neighbor == null) {
             unhighlight (plot);
         }
-    }
+    } 
     
     function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
-        var ins = checkIntersection(gridpos, plot);
-        if (ins && plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
-            plot.target.trigger('jqplotDataHighlight', ins);
-            highlight (plot, ins[0], ins[1]);
+        if (neighbor) {
+            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
+            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
+                plot.target.trigger('jqplotDataHighlight', ins);
+                highlight (plot, ins[0], ins[1]);
+            }
         }
-        else if (ins == null) {
+        else if (neighbor == null) {
             unhighlight (plot);
         }
     }
     }
     
     function handleClick(ev, gridpos, datapos, neighbor, plot) {
-        var intersection = checkIntersection(gridpos, plot);
-        if (intersection) {
-            plot.target.trigger('jqplotDataClick', intersection);
+        if (neighbor) {
+            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
+            plot.target.trigger('jqplotDataClick', ins);
         }
     }
     
     function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
-        var intersection = checkIntersection(gridpos, plot);
-        var idx = plot.plugins.donutRenderer.highlightedSeriesIndex;
-        if (idx != null && plot.series[idx].highlightMouseDown) {
-            unhighlight(plot);
+        if (neighbor) {
+            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
+            var idx = plot.plugins.donutRenderer.highlightedSeriesIndex;
+            if (idx != null && plot.series[idx].highlightMouseDown) {
+                unhighlight(plot);
+            }
+            plot.target.trigger('jqplotDataRightClick', ins);
         }
-        if (intersection) {
-            plot.target.trigger('jqplotDataRightClick', intersection);
-        }
-    }
-    
-    // function to check if event location is over a slice area
-    function checkIntersection(gridpos, plot) {
-        //figure out if over a slice
-        var series = plot.series;
-        var i, j, s, r, x, y, theta, sm, sa, minang, maxang;
-        for (i=0; i<series.length; i++) {
-            s = series[i];
-            sa = s.startAngle/180*Math.PI;
-            x = gridpos.x - s._center[0];
-            y = gridpos.y - s._center[1];
-            r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
-            if (x > 0 && -y >= 0) {
-                theta = 2*Math.PI - Math.atan(-y/x);
-            }
-            else if (x > 0 && -y < 0) {
-                theta = -Math.atan(-y/x);
-            }
-            else if (x < 0) {
-                theta = Math.PI - Math.atan(-y/x);
-            }
-            else if (x == 0 && -y > 0) {
-                theta = 3*Math.PI/2;
-            }
-            else if (x == 0 && -y < 0) {
-                theta = Math.PI/2;
-            }
-            else if (x == 0 && y == 0) {
-                theta = 0;
-            }
-            if (sa) {
-                theta -= sa;
-                if (theta < 0) {
-                    theta += 2*Math.PI;
-                }
-                else if (theta > 2*Math.PI) {
-                    theta -= 2*Math.PI;
-                }
-            }
-            
-            sm = s.sliceMargin/180*Math.PI;
-            if (r < s._radius && r > s._innerRadius) {
-                for (j=0; j<s.gridData.length; j++) {
-                    minang = (j>0) ? s.gridData[j-1][1]+sm : sm;
-                    maxang = s.gridData[j][1];
-                    if (theta > minang && theta < maxang) {
-                        return [s.index, j, s.gridData[j]];
-                    }
-                }
-            }
-        }
-        return null;
-    }
+    }    
     
     // called within context of plot
     // create a canvas which we can draw on.

src/plugins/jqplot.funnelRenderer.js

                 }
             }
         }
-        // set the _processGetNeighbor to false, we'll do this in the renderer.
-        this._processGetNeighbor = false;
         this.target.bind('mouseout', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
     }
     
     }
     
     function handleMove(ev, gridpos, datapos, neighbor, plot) {
-        var ins = checkIntersection(gridpos, plot);
-        if (ins) {
+        if (neighbor) {
+            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
             plot.target.trigger('jqplotDataMouseOver', ins);
             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
                 plot.target.trigger('jqplotDataHighlight', ins);
                 highlight (plot, ins[0], ins[1]);
             }
         }
-        else if (ins == null) {
+        else if (neighbor == null) {
             unhighlight (plot);
         }
     }
     
     function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
-        var ins = checkIntersection(gridpos, plot);
-        if (ins && plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
-            plot.target.trigger('jqplotDataHighlight', ins);
-            highlight (plot, ins[0], ins[1]);
+        if (neighbor) {
+            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
+            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
+                plot.target.trigger('jqplotDataHighlight', ins);
+                highlight (plot, ins[0], ins[1]);
+            }
         }
-        else if (ins == null) {
+        else if (neighbor == null) {
             unhighlight (plot);
         }
     }
     }
     
     function handleClick(ev, gridpos, datapos, neighbor, plot) {
-        var intersection = checkIntersection(gridpos, plot);
-        if (intersection) {
-            plot.target.trigger('jqplotDataClick', intersection);
+        if (neighbor) {
+            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
+            plot.target.trigger('jqplotDataClick', ins);
         }
     }
     
     function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
-        var intersection = checkIntersection(gridpos, plot);
-        var idx = plot.plugins.funnelRenderer.highlightedSeriesIndex;
-        if (idx != null && plot.series[idx].highlightMouseDown) {
-            unhighlight(plot);
+        if (neighbor) {
+            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
+            var idx = plot.plugins.funnelRenderer.highlightedSeriesIndex;
+            if (idx != null && plot.series[idx].highlightMouseDown) {
+                unhighlight(plot);
+            }
+            plot.target.trigger('jqplotDataRightClick', ins);
         }
-        if (intersection) {
-            plot.target.trigger('jqplotDataRightClick', intersection);
-        }
-    }
-    
-    // function to check if event location is over a area area
-    function checkIntersection(gridpos, plot) {
-        //figure out if over a area
-        var series = plot.series;
-        var i, j, s, r, x, y, theta, sm, sa, minang, maxang;
-        s = series[0];
-        x = gridpos.x;
-        y = gridpos.y;
-        var v = s._vertices,
-            vfirst = v[0],
-            vlast = v[v.length-1],
-            lex,
-            rex;
-        
-        // equations of right and left sides, returns x, y values given height of section (y value and 2 points)
-        
-        function findedge (l, p1 , p2) {
-            var m = (p1[1] - p2[1])/(p1[0] - p2[0]);
-            var b = p1[1] - m*p1[0];
-            var y = l + p1[1];
-            
-            return [(y - b)/m, y];
-        }
-        
-        // check each section
-        lex = findedge(y, vfirst[0], vlast[3]);
-        rex = findedge(y, vfirst[1], vlast[2]);
-        for (i=0; i<v.length; i++) {
-            cv = v[i];
-            if (y >= cv[0][1] && y <= cv[3][1] && x >= lex[0] && x <= rex[0]) {
-                return [s.index, i, s.data[i]];
-            }
-        }
-        
-        return null;
     }
     
     // called within context of plot