1. Chris Leonello
  2. jqplot
Issue #411 new

Highlighter & Cursor

Anonymous created an issue

First of all, thank you for this piece of beauty in this world of chaos.

I propose to combine highlighter and cursor plugins to make points highlighted when using: {{{

!javascript

cursor: { showVerticalLine: true, showTooltipDataPosition:true, show:true } }}}

I will try to code and post it.

Comments (2)

  1. Anonymous

    Did what I wanted to, sharing with you all.

    Code below is a highlighter plugin that has all ToolTip functionality stripped out (I use that of Cursor plugin as shown in question above), and which now serves one purpose: highlighting all the points under vertical line of cursor plugin (like that of Google Analytics).

    Modifications are only to highlighter plugin, cursor is left intact. All the code has just the things I don't need cut out; the added functionality is in handleMove function.

    /* stripped grimly by SmarT
     * jqPlot
     * Pure JavaScript plotting plugin using jQuery
     *
     * Version: 1.0.0b2_r792
     *
     * Copyright (c) 2009-2011 Chris Leonello
     * jqPlot is currently available for use in all personal or commercial projects 
     * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
     * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
     * choose the license that best suits your project and use it accordingly. 
     *
     * Although not required, the author would appreciate an email letting him 
     * know of any substantial use of jqPlot.  You can reach the author at: 
     * chris at jqplot dot com or see http://www.jqplot.com/info.php .
     *
     * If you are feeling kind and generous, consider supporting the project by
     * making a donation at: http://www.jqplot.com/donate.php .
     *
     * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
     *
     *     version 2007.04.27
     *     author Ash Searle
     *     http://hexmen.com/blog/2007/03/printf-sprintf/
     *     http://hexmen.com/js/sprintf.js
     *     The author (Ash Searle) has placed this code in the public domain:
     *     "This code is unrestricted: you are free to use it however you like."
     * 
     */
    (function($) {
        $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);
    
        $.jqplot.Highlighter = function(options) {
            // Group: Properties
            //
            //prop: show
            // true to show the highlight.
            this.show = $.jqplot.config.enablePlugins;
            // prop: markerRenderer
            // Renderer used to draw the marker of the highlighted point.
            // Renderer will assimilate attributes from the data point being highlighted,
            // so no attributes need set on the renderer directly.
            // Default is to turn off shadow drawing on the highlighted point.
            this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false});
            // prop: showMarker
            // true to show the marker
            this.showMarker  = true;
            // prop: lineWidthAdjust
            // Pixels to add to the lineWidth of the highlight.
            this.lineWidthAdjust = 2.5;
            // prop: sizeAdjust
            // Pixels to add to the overall size of the highlight.
            this.sizeAdjust = 5;
            // prop: showTooltip
            // Show a tooltip with data point values.
            this.yvalues = 1;
            this.isHighlighting = 0;
    
            $.extend(true, this, options);
        };
        
        // called with scope of plot
        $.jqplot.Highlighter.init = function (target, data, opts){
            var options = opts || {};
            // add a highlighter attribute to the plot
            this.plugins.highlighter = new $.jqplot.Highlighter(options.highlighter);
        };
        
        // called within scope of series
        $.jqplot.Highlighter.parseOptions = function (defaults, options) {
            // Add a showHighlight option to the series 
            // and set it to true by default.
            this.showHighlight = true;
        };
        
        // called within context of plot
        // create a canvas which we can draw on.
        // insert it before the eventCanvas, so eventCanvas will still capture events.
        $.jqplot.Highlighter.postPlotDraw = function() {
            // Memory Leaks patch    
            if (this.plugins.highlighter && this.plugins.highlighter.highlightCanvas) {
                this.plugins.highlighter.highlightCanvas.resetCanvas();
                this.plugins.highlighter.highlightCanvas = null;
            }
    
            this.plugins.highlighter.highlightCanvas = new $.jqplot.GenericCanvas();
            
            this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding, 'jqplot-highlight-canvas', this._plotDimensions, this));
            this.plugins.highlighter.highlightCanvas.setContext();
        };
        
        $.jqplot.preInitHooks.push($.jqplot.Highlighter.init);
        $.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Highlighter.parseOptions);
        $.jqplot.postDrawHooks.push($.jqplot.Highlighter.postPlotDraw);
        
        function draw(plot, neighbor) {
            var hl = plot.plugins.highlighter;
            var s = plot.series[neighbor.seriesIndex];
            var smr = s.markerRenderer;
            var mr = hl.markerRenderer;
            mr.style = smr.style;
            mr.lineWidth = smr.lineWidth + hl.lineWidthAdjust;
            mr.size = smr.size + hl.sizeAdjust;
            var rgba = $.jqplot.getColorComponents(smr.color);
            var newrgb = [rgba[0], rgba[1], rgba[2]];
            var alpha = (rgba[3] >= 0.6) ? rgba[3]*0.6 : rgba[3]*(2-rgba[3]);
            mr.color = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+alpha+')';
            mr.init();
            mr.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], hl.highlightCanvas._ctx);
        }
        
        function handleMove(ev, gridpos, datapos, neighbor, plot) {
            var hl = plot.plugins.highlighter;
            if (hl.show) {
    			var clear = false;
    			
    			// extend neighbor
    			if (neighbor == null) {
    				var gd = plot.series[0].gridData;
    				var th = plot.plugins.cursor.intersectionThreshold + plot.series[0].markerRenderer.size/2;
    				
    				for (var i = 0; i < plot.series[0].gridData.length; i++) {
    					if (Math.abs(gd[i][0] - gridpos.x) <= th) {
    						// got a hit
    						neighbor = {
    							seriesIndex: 0,
    							pointIndex: i,
    							gridData: {x:gd[i].x, y:gd[i].y},
    							data: {}
    						};
    					}
    				}
    			}
    			
    			if (neighbor == null) {
    				if (hl.isHighlighting > 0) clear = true;
    			} else if (hl.isHighlighting != neighbor.pointIndex+1) {
    				clear = true;
    			}
                if (clear) {
                   var ctx = hl.highlightCanvas._ctx;
                   ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
                   hl.isHighlighting = 0;
            	  ctx = null;
                
                }
                if (neighbor != null && plot.series[neighbor.seriesIndex].showHighlight && !hl.isHighlighting) {
                    hl.isHighlighting = neighbor.pointIndex+1;
                    if (hl.showMarker) {
    					for (var i = 0; i < plot.series.length; i++) {
    						var sibling = $.extend({},neighbor);
    						sibling.seriesIndex = i;
    						draw(plot,sibling);
    					}
                    }
                }
            }
        }
    })(jQuery);
    

    Sorry for such a poorly commented - don't have much time, so decided that better share as is than not share at all (I know many of you will disagree :)). Thanks, Chris and all those helping with development.

  2. Anonymous

    Thanks for This!

    Question: How do you get "sticky" tooltips (which stick to the marker) for this? I can only seem to get it to work for the marker itself, but I would really love to know how to integrate the tooltip to show even when the marker is not directly hovered over. I think that the neighbor array carries this information (the mouse position is supplemented when the user is not over a marker.... meaning that if I can change the "ShowToolTip" function to recognize the neighbor code, instead of the actual mouse position - it should work!

  3. Log in to comment