Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jqplot format tooltip values

I want to have a tooltip hover highlight thingy in jqplot. The problem is that I want it to give more detail then on the axes. So the formatter should be different. I can't get it to display the seconds to:

There's a JS fidle here!

I want the timestamp to display as hours:minutes:seconds, which would be format string '%H:%M:%S' or '%T' or '%X'. But how do I do that?

    highlighter: {
        show: true,
        sizeAdjust: 3,
        //useAxesFormatters: false,
        //tooltipFormatString: '%H:%M:%S',
        formatString: '<table class="jqplot-highlighter"><tr><td>tijd:</td><td>%s</td></tr><tr><td>snelheid:</td><td>%s</td></tr></table>',
    },
like image 387
Jeroen Avatar asked May 14 '12 15:05

Jeroen


3 Answers

I tried to use coma's answer but first modified it to:

return jqPlot.series[seriesIndex]._plotData[pointIndex][0];

which is a hack (because it uses _plotData) and then changed it to

return jqPlot.data[seriesIndex][pointIndex][0];

which should be okay.

like image 77
Alexander Avatar answered Nov 13 '22 00:11

Alexander


This question is old, but I was looking for the same and there is an options (even in the version used here) to do it:

http://jsfiddle.net/coma/DWFTb/151/

highlighter: {
    show: true,
    sizeAdjust: 3,
    tooltipContentEditor: function(str, seriesIndex, pointIndex, jqPlot) {

        return series[seriesIndex][pointIndex][0];

    }
}...

I hope this help others.

like image 38
coma Avatar answered Nov 13 '22 01:11

coma


I was looking for same question, unfortunately no answer yet. The ugly solution that I came with is, modify the jqplot.highlighter.js to get what I wanted. Here is how, I accomplished this,

Declare xAxisFormatString and yAxisFormatString properties

// prop: xAxisFormatString
// If this is provided then it will override the axesformatter format string
this.xAxisFormatString = '';
// prop: xAxisFormatString
// If this is provided then it will override the axesformatter format string
this.yAxisFormatString = '';

Then at showtooltip method use this instead of axes format string

var xfstr = series._xaxis._ticks[0].formatString;
if('' != hl.xAxisFormatString) {
    xfstr = hl.xAxisFormatString;
}
var yfstr = series._yaxis._ticks[0].formatString;
if('' != hl.yAxisFormatString) {
    yfstr = hl.yAxisFormatString;
}

When calling the graph,

highlighter: {
    show: true,
    useAxesFormatters: true,
    xAxisFormatString: '%m-%Y',
    formatString: 'hi - %s',
    sizeAdjust: 7.5
},

I have the useAxesFormatters true because i don't want to mess with the tooltipformatstring. I am okay to use the same formatter but I would like to override the formatstring. this way I got it working.

Here is the complete jqplot.highlighter.js

/**
* 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]);

    /**
    * 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: 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; tooltipContentEditor
    // Function used to edit/augment/replace the formatted tooltip contents.
    // Called as str = tooltipContentEditor(str, seriesIndex, pointIndex)
    // where str is the generated tooltip html and seriesIndex and pointIndex identify
    // the data point being highlighted. Should return the html for the tooltip contents.
    this.tooltipContentEditor = null;
    // prop: useAxesFormatters
    // Use the x and y axes formatters to format the text in the tooltip.
    this.useAxesFormatters = true;
// prop: xAxisFormatString
// If this is provided then it will override the axesformatter format string
this.xAxisFormatString = '';
// prop: xAxisFormatString
// If this is provided then it will override the axesformatter format string
this.yAxisFormatString = '';
    // 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);
};

var locations = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'];
var locationIndicies = {'nw':0, 'n':1, 'ne':2, 'e':3, 'se':4, 's':5, 'sw':6, 'w':7};
var oppositeLocations = ['se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'];

// 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() {
    // Memory Leaks patch    
    if (this.plugins.highlighter && this.plugins.highlighter.highlightCanvas) {
        this.plugins.highlighter.highlightCanvas.resetCanvas();
        this.plugins.highlighter.highlightCanvas = null;
    }

    if (this.plugins.highlighter && this.plugins.highlighter._tooltipElem) {
        this.plugins.highlighter._tooltipElem.emptyForce();
        this.plugins.highlighter._tooltipElem = 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();

    var elem = document.createElement('div');
    this.plugins.highlighter._tooltipElem = $(elem);
    elem = null;
    this.plugins.highlighter._tooltipElem.addClass('jqplot-highlighter-tooltip');
    this.plugins.highlighter._tooltipElem.css({position:'absolute', display:'none'});
    
    this.eventCanvas._elem.before(this.plugins.highlighter._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; 
    if('' != hl.xAxisFormatString)
    xfstr = hl.xAxisFormatString;
        var yfstr = series._yaxis._ticks[0].formatString;
    if('' != hl.yAxisFormatString)
    yfstr = hl.yAxisFormatString;
        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);
                    ystrs.unshift(hl.formatString);
                    str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);
                    break;
                case 'yx':
                    ystrs.push(xstr);
                    ystrs.unshift(hl.formatString);
                    str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);
                    break;
                case 'x':
                    str = $.jqplot.sprintf.apply($.jqplot.sprintf, [hl.formatString, xstr]);
                    break;
                case 'y':
                    ystrs.unshift(hl.formatString);
                    str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);
                    break;
                default: // same as xy
                    ystrs.unshift(xstr);
                    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 = ystrs.join(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]);
        } 
    }
    if ($.isFunction(hl.tooltipContentEditor)) {
        // args str, seriesIndex, pointIndex are essential so the hook can look up
        // extra data for the point.
        str = hl.tooltipContentEditor(str, neighbor.seriesIndex, neighbor.pointIndex, plot);
    }
    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;
    }
    
    var loc = locations;
    if (series.fillToZero && series.fill && neighbor.data[1] < 0) {
        loc = oppositeLocations;
    }
    
    switch (loc[locationIndicies[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();
    }
    elem = null;
    
}

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;
            ctx = null;
        
        }
        else 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)) {
                showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor);
            }
            if (hl.bringSeriesToFront) {
                plot.moveSeriesToFront(neighbor.seriesIndex);
            }
        }
    }
}
})(jQuery);
like image 45
Senthilkumar Elangovan Avatar answered Nov 13 '22 01:11

Senthilkumar Elangovan