Enable highlighter tooltip to display label of the series on dot

Anonymous avatarAnonymous created an issue

Display the label of the serie on the dot tooltip.

Example :

    var series =  [
     [3,2,1,1,3,3,2,1,2],
     [4,4,6,11,13,13,15,15,15] ]
    ];

    var options = {
        series:[
           {label:'serie name 1'},
           {label:'serie name 2'}
        ],
    highlighter: {
       tooltipAxes: 'x',
       formatString:'#serieLabel# - %s'
    }
    };

The #serieLabel# should be replace by the label of the serie

Comments (14)

  1. Anonymous

    A patch for the jqplot.highlighter.js plugin.

    Add in function showTooltip(plot, series, neighbor) { ... }

    str = str.replace(/#serieLabel#/,series.label);
    

    before

    elem.html(str);
    
  2. Anonymous

    A patch for the jqplot.highlighter.js plugin.

    Add in function showTooltip(plot, series, neighbor) { ... }

    str = str.replace(/#serieLabel#/,series.label);
    

    before

    elem.html(str);
    
  3. Chris Leonello

    There is a need to make tooltip formatting generally more flexible and consistent among plugins. It would probably allow more flexibility than discussed here. I am currently in the planning stage for this.

  4. Anonymous

    Hi,,

    I'm interested in this feature but something different. i wanted to display axis.tick value in FormatString function of Hightlighter

    Khushi

  5. Anonymous

    Problem: When using the Highlighter plugin, jqPlot is not capable of displaying a tooltip containing information about the series, i.e. series labels, axis ticks.

    Workaround:

    1. handle the jqplotMouseMove event. Store the position of the mouse in mouseX and mouseY. 2. Create a copy of jqplot.highlighter.js called jqplot.highlighter.workaround.js. 3. In jqplot.highlighter.workaround.js, change function showTooltip() as follows (See 'ADD THIS->'...):

    function showTooltip(plot, series, neighbor) { neighbor looks like: {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]} gridData should be x,y pixel coords on the grid. add the plot._gridPadding to that to get x,y in the target.

    ADD THIS-> var evt = jQuery.Event('jqplotDataHighlight'); evt.pageX = neighbor.gridData[0]; evt.pageY = neighbor.gridData[1]; var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; plot.target.trigger(evt, ins); return; <- ADD THIS

    var hl = plot.plugins.highlighter; . . .

    4. In jqplot.highlighter.workaround.js, change function handleMove() as follows (See 'ADD THIS->'...):

    function handleMove(ev, gridpos, datapos, neighbor, plot) { var hl = plot.plugins.highlighter; var c = plot.plugins.cursor; if (hl.show) { if (neighbor == null && hl.isHighlighting) { var ctx = hl.highlightCanvas._ctx; ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); if (hl.fadeTooltip) { hl._tooltipElem.fadeOut(hl.tooltipFadeSpeed); } else { hl._tooltipElem.hide(); } if (hl.bringSeriesToFront) { plot.restorePreviousSeriesOrder(); } hl.isHighlighting = false;

    ADD THIS-> var evt = jQuery.Event('jqplotDataUnhighlight'); plot.target.trigger(evt); return; <- ADD THIS } if (neighbor != null && plot.series[neighbor.seriesIndex].showHighlight && !hl.isHighlighting) { . . .

    5. Handle the events jqplotDataHighlight and jqplotDataUnhighlight as follows:

    $('#chart').bind('jqplotMouseMove', function (ev) { mouseX = ev.pageX; mouseY = ev.pageY; } );

    $('#chart').bind('jqplotDataHighlight', function (ev, seriesIndex, pointIndex, data) { $('#tooltip').html(seriesLabels[seriesIndex].label + ' ' + xAxisTicks[pointIndex] + ' ' + parseFloat(data.toString().split(',')[1]).toFixed(2)).css('display', '').css('left', (mouseX + 25) + 'px').css('top', (mouseY - 25) + 'px'); } );

    $('#chart').bind('jqplotDataUnhighlight', function (ev) { $('#tooltip').css('display', 'none'); } );

    6. Add the tooltip div to your page as follows:

    <div id="tooltip" style="display: none; width: 64; height: 48; position: absolute; left: 0px; top: 0px;"></div>

  6. Anonymous

    I changed the File as follows:

    PS: showLabel must be set to true to activate it. Then use %s in the "formatString".

    highlighter: {
        show: true,
        showLabel: true,
        formatString: '%s - %d. X, %d Y'
    }
    
    /**
     * Copyright (c) 2009 - 2010 Chris Leonello
     * jqPlot is currently available for use in all personal or commercial projects 
     * under both the MIT and GPL version 2.0 licenses. This means that you can 
     * choose the license that best suits your project and use it accordingly. 
     *
     * 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 .  This is, of course, 
     * not required.
     *
     * If you are feeling kind and generous, consider supporting the project by
     * making a donation at: http://www.jqplot.com/donate.php .
     *
     * Thanks for using jqPlot!
     * 
     */
    (function($) {
        $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);
        
        /**
         * Class: $.jqplot.Highlighter
         * Plugin which will highlight data points when they are moused over.
         * 
         * To use this plugin, include the js
         * file in your source:
         * 
         * > <script type="text/javascript" src="plugins/jqplot.highlighter.js"></script>
         * 
         * A tooltip providing information about the data point is enabled by default.
         * To disable the tooltip, set "showTooltip" to false.
         * 
         * You can control what data is displayed in the tooltip with various
         * options.  The "tooltipAxes" option controls wether the x, y or both
         * data values are displayed.
         * 
         * Some chart types (e.g. hi-low-close) have more than one y value per
         * data point. To display the additional values in the tooltip, set the
         * "yvalues" option to the desired number of y values present (3 for a hlc chart).
         * 
         * By default, data values will be formatted with the same formatting
         * specifiers as used to format the axis ticks.  A custom format code
         * can be supplied with the tooltipFormatString option.  This will apply 
         * to all values in the tooltip.  
         * 
         * For more complete control, the "formatString" option can be set.  This
         * Allows conplete control over tooltip formatting.  Values are passed to
         * the format string in an order determined by the "tooltipAxes" and "yvalues"
         * options.  So, if you have a hi-low-close chart and you just want to display 
         * the hi-low-close values in the tooltip, you could set a formatString like:
         * 
         * > highlighter: {
         * >     tooltipAxes: 'y',
         * >     yvalues: 3,
         * >     formatString:'<table class="jqplot-highlighter">
         * >         <tr><td>hi:</td><td>%s</td></tr>
         * >         <tr><td>low:</td><td>%s</td></tr>
         * >         <tr><td>close:</td><td>%s</td></tr></table>'
         * > }
         * 
         */
        $.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: showLabel
            // true to show the label
            this.showLabel = 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.showTooltip = true;
            // prop: tooltipLocation
            // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'
            this.tooltipLocation = 'nw';
            // prop: fadeTooltip
            // true = fade in/out tooltip, flase = show/hide tooltip
            this.fadeTooltip = true;
            // prop: tooltipFadeSpeed
            // 'slow', 'def', 'fast', or number of milliseconds.
            this.tooltipFadeSpeed = "fast";
            // prop: tooltipOffset
            // Pixel offset of tooltip from the highlight.
            this.tooltipOffset = 2;
            // prop: tooltipAxes
            // Which axes to display in tooltip, 'x', 'y' or 'both', 'xy' or 'yx'
            // 'both' and 'xy' are equivalent, 'yx' reverses order of labels.
            this.tooltipAxes = 'both';
            // prop; tooltipSeparator
            // String to use to separate x and y axes in tooltip.
            this.tooltipSeparator = ', ';
            // prop: useAxesFormatters
            // Use the x and y axes formatters to format the text in the tooltip.
            this.useAxesFormatters = true;
            // prop: tooltipFormatString
            // sprintf format string for the tooltip.
            // Uses Ash Searle's javascript sprintf implementation
            // found here: http://hexmen.com/blog/2007/03/printf-sprintf/
            // See http://perldoc.perl.org/functions/sprintf.html for reference.
            // Additional "p" and "P" format specifiers added by Chris Leonello.
            this.tooltipFormatString = '%.5P';
            // prop: formatString
            // alternative to tooltipFormatString
            // will format the whole tooltip text, populating with x, y values as
            // indicated by tooltipAxes option.  So, you could have a tooltip like:
            // 'Date: %s, number of cats: %d' to format the whole tooltip at one go.
            // If useAxesFormatters is true, values will be formatted according to
            // Axes formatters and you can populate your tooltip string with 
            // %s placeholders.
            this.formatString = null;
            // prop: yvalues
            // Number of y values to expect in the data point array.
            // Typically this is 1.  Certain plots, like OHLC, will
            // have more y values in each data point array.
            this.yvalues = 1;
            // prop: bringSeriesToFront
            // This option requires jQuery 1.4+
            // True to bring the series of the highlighted point to the front
            // of other series.
            this.bringSeriesToFront = false;
            this._tooltipElem;
            this.isHighlighting = false;
    
            $.extend(true, this, options);
        };
        
        // axis.renderer.tickrenderer.formatter
        
        // 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() {
            this.plugins.highlighter.highlightCanvas = new $.jqplot.GenericCanvas();
            
            this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding, 'jqplot-highlight-canvas', this._plotDimensions));
            var hctx = this.plugins.highlighter.highlightCanvas.setContext();
            
            var p = this.plugins.highlighter;
            p._tooltipElem = $('<div class="jqplot-highlighter-tooltip" style="position:absolute;display:none"></div>');
            this.eventCanvas._elem.before(p._tooltipElem);
        };
        
        $.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 showTooltip(plot, series, neighbor) {
            // neighbor looks like: {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}
            // gridData should be x,y pixel coords on the grid.
            // add the plot._gridPadding to that to get x,y in the target.
            var hl = plot.plugins.highlighter;
            var elem = hl._tooltipElem;
            if (hl.useAxesFormatters) {
                var xf = series._xaxis._ticks[0].formatter;
                var yf = series._yaxis._ticks[0].formatter;
                var xfstr = series._xaxis._ticks[0].formatString;
                var yfstr = series._yaxis._ticks[0].formatString;
                var str;
                var xstr = xf(xfstr, neighbor.data[0]);
                var ystrs = [];
                for (var i=1; i<hl.yvalues+1; i++) {
                    ystrs.push(yf(yfstr, neighbor.data[i]));
                }
                if (hl.formatString) {
                    switch (hl.tooltipAxes) {
                        case 'both':
                        case 'xy':
                            ystrs.unshift(xstr);
                            if (hl.showLabel) {
                                ystrs.unshift(neighbor.label);
                            }
                            ystrs.unshift(hl.formatString);
                            str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);
                            break;
                        case 'yx':
                            ystrs.push(xstr);
                            if (hl.showLabel) {
                                ystrs.unshift(neighbor.label);
                            }
                            ystrs.unshift(hl.formatString);
                            str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);
                            break;
                        case 'x':
                            if (hl.showLabel) {
                                str = $.jqplot.sprintf.apply($.jqplot.sprintf, [hl.formatString, neighbor.label, xstr]);
                            }
                            else {
                                str = $.jqplot.sprintf.apply($.jqplot.sprintf, [hl.formatString, xstr]);
                            }
                            break;
                        case 'y':
                            if (hl.showLabel) {
                                ystrs.unshift(neighbor.label);
                            }
                            ystrs.unshift(hl.formatString);
                            str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);
                            break;
                        default: // same as xy
                            ystrs.unshift(xstr);
                            if (hl.showLabel) {
                                ystrs.unshift(neighbor.label);
                            }
                            ystrs.unshift(hl.formatString);
                            str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);
                            break;
                    } 
                }
                else {
                    switch (hl.tooltipAxes) {
                        case 'both':
                        case 'xy':
                            str = xstr;
                            for (var i=0; i<ystrs.length; i++) {
                                str += hl.tooltipSeparator + ystrs[i];
                            }
                            break;
                        case 'yx':
                            str = '';
                            for (var i=0; i<ystrs.length; i++) {
                                str += ystrs[i] + hl.tooltipSeparator;
                            }
                            str += xstr;
                            break;
                        case 'x':
                            str = xstr;
                            break;
                        case 'y':
                            str = '';
                            for (var i=0; i<ystrs.length; i++) {
                                str += ystrs[i] + hl.tooltipSeparator;
                            }
                            break;
                        default: // same as 'xy'
                            str = xstr;
                            for (var i=0; i<ystrs.length; i++) {
                                str += hl.tooltipSeparator + ystrs[i];
                            }
                            break;
                        
                    }                
                }
            }
            else {
                var str;
                if (hl.tooltipAxes == 'both' || hl.tooltipAxes == 'xy') {
                    str = $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[0]) + hl.tooltipSeparator + $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[1]);
                }
                else if (hl.tooltipAxes == 'yx') {
                    str = $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[1]) + hl.tooltipSeparator + $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[0]);
                }
                else if (hl.tooltipAxes == 'x') {
                    str = $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[0]);
                }
                else if (hl.tooltipAxes == 'y') {
                    str = $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[1]);
                } 
            }
            elem.html(str);
            var gridpos = {x:neighbor.gridData[0], y:neighbor.gridData[1]};
            var ms = 0;
            var fact = 0.707;
            if (series.markerRenderer.show == true) { 
                ms = (series.markerRenderer.size + hl.sizeAdjust)/2;
            }
            switch (hl.tooltipLocation) {
                case 'nw':
                    var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - hl.tooltipOffset - fact * ms;
                    var y = gridpos.y + plot._gridPadding.top - hl.tooltipOffset - elem.outerHeight(true) - fact * ms;
                    break;
                case 'n':
                    var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
                    var y = gridpos.y + plot._gridPadding.top - hl.tooltipOffset - elem.outerHeight(true) - ms;
                    break;
                case 'ne':
                    var x = gridpos.x + plot._gridPadding.left + hl.tooltipOffset + fact * ms;
                    var y = gridpos.y + plot._gridPadding.top - hl.tooltipOffset - elem.outerHeight(true) - fact * ms;
                    break;
                case 'e':
                    var x = gridpos.x + plot._gridPadding.left + hl.tooltipOffset + ms;
                    var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
                    break;
                case 'se':
                    var x = gridpos.x + plot._gridPadding.left + hl.tooltipOffset + fact * ms;
                    var y = gridpos.y + plot._gridPadding.top + hl.tooltipOffset + fact * ms;
                    break;
                case 's':
                    var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
                    var y = gridpos.y + plot._gridPadding.top + hl.tooltipOffset + ms;
                    break;
                case 'sw':
                    var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - hl.tooltipOffset - fact * ms;
                    var y = gridpos.y + plot._gridPadding.top + hl.tooltipOffset + fact * ms;
                    break;
                case 'w':
                    var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - hl.tooltipOffset - ms;
                    var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
                    break;
                default: // same as 'nw'
                    var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - hl.tooltipOffset - fact * ms;
                    var y = gridpos.y + plot._gridPadding.top - hl.tooltipOffset - elem.outerHeight(true) - fact * ms;
                    break;
            }
            elem.css('left', x);
            elem.css('top', y);
            if (hl.fadeTooltip) {
                // Fix for stacked up animations.  Thnanks Trevor!
                elem.stop(true,true).fadeIn(hl.tooltipFadeSpeed);
            }
            else {
                elem.show();
            }
            
        }
        
        function handleMove(ev, gridpos, datapos, neighbor, plot) {
            var hl = plot.plugins.highlighter;
            var c = plot.plugins.cursor;
            if (hl.show) {
                if (neighbor == null && hl.isHighlighting) {
                   var ctx = hl.highlightCanvas._ctx;
                   ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
                    if (hl.fadeTooltip) {
                        hl._tooltipElem.fadeOut(hl.tooltipFadeSpeed);
                    }
                    else {
                        hl._tooltipElem.hide();
                    }
                    if (hl.bringSeriesToFront) {
                        plot.restorePreviousSeriesOrder();
                    }
                   hl.isHighlighting = false;
                
                }
                if (neighbor != null && plot.series[neighbor.seriesIndex].showHighlight && !hl.isHighlighting) {
                    hl.isHighlighting = true;
                    if (hl.showMarker) {
                        draw(plot, neighbor);
                    }
                    if (hl.showTooltip && (!c || !c._zoom.started)) {
                        if (hl.showLabel) {
                            neighbor.label = plot.series[neighbor.seriesIndex].label;
                        }
                        showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor);
                    }
                    if (hl.bringSeriesToFront) {
                        plot.moveSeriesToFront(neighbor.seriesIndex);
                    }
                }
            }
        }
    })(jQuery);
    
  7. Anonymous

    Hello, I am trying to get the series label into the tooltip.

    the enhanced tooltip with .bind('jqplotDataHighlight') does work if I want to display the ticks and data, but when I try to show the the labels of the series like in the post above with "seriesLabels[seriesIndex].label" I get nothing.

    $('#chartdiv').bind('jqplotDataHighlight', 
            function (ev, seriesIndex, pointIndex, data ) {
                mouseX = ev.pageX; //these are going to be how jquery knows where to put the div that will be our tooltip
                mouseY = ev.pageY;
                $('#info').show().html(seriesLabels[seriesIndex].label + ', ' + data[1] ');
                var cssObj = {
                      'position' : 'fixed',
    				  'z-index' : '4',
                      'font-weight' : 'bold',
                      'left' : mouseX-430 + 'px', //usually needs more offset here
                      'top' : mouseY + 'px'
                    };
                $('#info').css(cssObj);
                }
        );    
    

    Any suggestion would be appreciated. thanks

  8. Miguel Garcia Dominguez

    In the latest version I have found in the repository (version 1.0.1, Revision 1096), Highlighter triggers jqplotHighlighterHighlight and jqplotHighlighterUnhighlight so you might want to bind to those if that's the version of the plugin you are using.

    It works for me, but be aware that the event is triggered before the tooltip is rendered so any change you do to the DOM will be replaced. I had to move the lines that trigger the events (plot.target.trigger(...) to the end of each block of the handleMove function and add it to the third case as well cause that one was not triggering anything.

    Hope it helps.

  9. Gilles Bourdeau

    Hi, I'd like the highlighter tooltip to display also point labels from extra series data, has someone tried this before ? My goal is to show a comment when you highlight a point (to explain the variations of the line). Thanks in advance...

  10. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.